/*
这个实现的是一个简单的时间轮的代码，这个代码可以实现定时器的功能，作为一个中间件存在与项目之中
*/
#pragma once
#include <time.h>
#include <functional>
#include <iostream>
#include <cstdlib> // 用于 rand() 和 srand()
#include <ctime>   // 用于 time()
#include <string>
#include <signal.h>
#include <netinet/in.h>
#define MAX_SIZE 1024
#define TIME_WHEEL_NUM 60
#define TIME_WHEEL_TS 1
// 从时间轮开始创造的时候，有一个cur_slot对应当前在处理的槽，每一次进行tick处理的时候，都去执行当前节点的定时器链表，所以外部的定时信号以1秒为单位

namespace zj
{
    struct tw_timer;
    struct client_data
    {

        int getsockfd()
        {
            return sockfd;
        }
        void setaddr(sockaddr_in addr1)
        {
            std::cout << "setaddr(sockaddr_in addr1)" << std::endl;
            addr = addr1;
            std::cout << "setaddr(sockaddr_in addr1)" << std::endl;
        }
        int sockfd;
        std::string buffer;
        // char buffer[MAX_SIZE];
        sockaddr_in addr;
        tw_timer *timer;
    };
    using func_t = std::function<void(client_data *)>;
    struct tw_timer
    {
        tw_timer(int rotation, int ts) // 下几次进行处理 ， 存放在第几个槽
            : _rotation(rotation), _ts(ts)
        {
        }
        /*
            最关键的是，rotation记录自己是向后第几圈     ts记录自己在第几个槽的链表

        */
        func_t handler;
        client_data *cli; // 用来在最后清除定时器的时候，将用户的数据最后一并清除
        int _rotation;    //
        int _ts;          // 放在第几个槽

        tw_timer *prev;
        tw_timer *next;
    };

    class Time_Wheel // 这是一个时间轮，用来管理定时任务
    {
    public:
        Time_Wheel()
        {
        }

        // timeout表示定时多少秒被处理 ，插入哪个槽，都以cur_slot作为参考系
        tw_timer *add_timer(tw_timer *timer) // 0<t<2属于第一个槽  60<=t<31属于第0个槽
        {
            if (timer == nullptr)
            {
                return nullptr;
            }

            if (!slots[timer->_ts])
            {
                // 此时代表slot处还没有头节点
                printf("插入定时器节点，rotation is: %d,slot is %d,cur_slot is: %d,", timer->_rotation, timer->_ts, cur_slot);
                slots[timer->_ts] = timer;
                timer->next = nullptr;
            }
            else
            {
                // 此时代表slot处有了头节点
                printf("插入定时器节点，rotation is: %d,slot is %d,cur_slot is: %d,", timer->_rotation, timer->_ts, cur_slot);
                timer->next = slots[timer->_ts];
                slots[timer->_ts]->prev = timer;
                slots[timer->_ts] = timer;
            }
            return timer;
        }

        int get_cur_slot()
        {
            return cur_slot;
        }

        tw_timer *get_timer(int timeout)
        {
            if (timeout == 0)
            {
                return nullptr;
            }
            int ticks = 0;    /// 注意这个ticks  用来记录rotation
            if (timeout < TS) // 当前槽以1s为一个单位
            {
                ticks = 1;
            }
            else
            {
                ticks = timeout / TS;
            }
            int rotation = ticks / N;                // 这个用来表示接下来rotation圈执行定时任务
            int slot = (cur_slot + (ticks % N)) % N; // 这个用来表示插入到第几个槽
            tw_timer *timer = new tw_timer(rotation, slot);
            return timer;
        }

        tw_timer *add_timer(int timeout) // 0<t<2属于第一个槽  60<=t<31属于第0个槽   timeout不表示绝对时间，表示定时的秒数
        {
            if (timeout == 0)
            {
                return nullptr;
            }
            int ticks = 0;    /// 注意这个ticks  用来记录rotation
            if (timeout < TS) // 当前槽以1s为一个单位
            {
                ticks = 1;
            }
            else
            {
                ticks = timeout / TS;
            }
            int rotation = ticks / N;                // 这个用来表示接下来rotation圈执行定时任务
            int slot = (cur_slot + (ticks % N)) % N; // 这个用来表示插入到第几个槽
            tw_timer *timer = new tw_timer(rotation, slot);
            if (!slots[slot])
            {
                // 此时代表slot处还没有头节点
                printf("插入定时器节点，rotation is: %d,slot is %d,cur_slot is: %d,", rotation, slot, cur_slot);
                slots[slot] = timer;
                timer->next = nullptr;
            }
            else
            {
                // 此时代表slot处有了头节点
                printf("插入定时器节点，rotation is: %d,slot is %d,cur_slot is: %d,", rotation, slot, cur_slot);
                timer->next = slots[slot];
                slots[slot]->prev = timer;
                slots[slot] = timer;
            }
            return timer;
        }

        void del_timer(tw_timer *timer)
        {
            if (!timer)
            {
                return;
            }
            // 清除一个timer定时器节点
            int TS = timer->_ts;
            // 1 .当timer是头节点时
            if (slots[TS] == timer)
            {
                slots[TS] = timer->next;
                // 又有两种情况，1.timer不是唯一节点
                if (slots[TS])
                {
                    slots[TS]->prev = nullptr;
                }
                // 2.timer是唯一节点,不做特殊处理了
                delete timer;
            }

            // 2 .timer不是头节点时
            else
            {
                timer->prev->next = timer->next;
                if (timer->next)
                {
                    // a. timer不是尾节点
                    timer->next->prev = timer->prev;
                }
                delete timer;
            }
        }

        void adjust_timer(tw_timer *timer, int new_timeout)
        {
            if (!timer || new_timeout <= 0)
            {
                return;
            }

            // 先从当前位置删除定时器
            int old_slot = timer->_ts;
            if (slots[old_slot] == timer) // 如果这个timer是头节点
            {
                slots[old_slot] = timer->next;
                if (slots[old_slot]) // 如果timer既是头节点也是最后一个节点的话
                {
                    slots[old_slot]->prev = nullptr;
                }
            }
            else if (timer->prev != nullptr) // 这个timer不是头节点
            {
                timer->prev->next = timer->next;
                if (timer->next) // 这个timer不是头节点，但是是最后一个节点
                {
                    timer->next->prev = timer->prev;
                }
            }

            // 计算新的位置
            int ticks = new_timeout < TS ? 1 : new_timeout / TS;
            int rotation = ticks / N;
            int new_slot = (cur_slot + (ticks % N)) % N;

            // 更新定时器的属性
            timer->_rotation = rotation;
            timer->_ts = new_slot;
            timer->prev = nullptr;
            timer->next = nullptr;

            // 重新添加到时间轮
            add_timer(timer);

            printf("调整定时器位置成功，新位置: rotation=%d, slot=%d\n", rotation, new_slot);
        }

        void tick() // 每一次alarm信号触发，会调用一次tick，tick每次都清除当前cur_slot所指向链表中rotation为0的定时器，执行对应的定时任务
        {           //
            printf("alarm信号到来，当前cur_slot is: %d\n", cur_slot);
            tw_timer *timer = slots[cur_slot]; // 当前需要处理的链表头节点
            if (!timer)
            {
                printf("alarm信号到来,当前cur_slot没有需要处理的定时器\n");
                cur_slot = (cur_slot + 1) % N;
            }
            // 需要一个一个去遍历，删除rotation为0的定时器
            while (timer)
            {
                static int count = 0;
                count++;
                std::cout << "进来count: " << count << "次";
                if (timer->_rotation > 0)
                {
                    timer->_rotation--;
                    timer = timer->next;
                }
                else // 此时rotation都为0
                {
                    if (timer == nullptr)
                        break;
                    std::cout << "到了,fatal error" << std::endl;
                    timer->handler(timer->cli); // 调用定时器处理函数   1.处理客户端关闭连接和正常定时器任务结束时都需要调用这个定时器处理函数

                    // 有两种情况，一种timer是头节点，一种timer不是头节点
                    if (slots[cur_slot] == timer)
                    {
                        std::cout << "进了timer是头节点" << std::endl;
                        slots[cur_slot] = timer->next;
                        // 又有两种情况，1.timer不是唯一节点
                        if (slots[cur_slot])
                        {
                            slots[cur_slot]->prev = nullptr;
                        }
                        // 2.timer是唯一节点,不做特殊处理了
                        delete timer;
                        timer = nullptr;
                    }
                    else if (slots[cur_slot] != timer)
                    {
                        // timer不是头节点   注意timer是否是尾节点
                        tw_timer *timer2 = timer->next;
                        timer->prev->next = timer2;
                        if (timer2)
                        {
                            // a. timer不是尾节点
                            timer->next->prev = timer->prev;
                        }
                        delete timer;
                        timer = timer2;
                    }
                }
            }
            cur_slot = (++cur_slot) % N;
        }

        ~Time_Wheel()
        {
            // 清空整个时间轮
            for (int i = 0; i < N; i++)
            {
                if (!slots[i])
                {
                    continue;
                }
                else
                {
                    tw_timer *timer = slots[i];

                    while (timer)
                    {
                        tw_timer *timer2 = timer->next; // 每次更新新的timer2

                        delete timer;
                        timer = timer2;
                    }
                }
            }
        }

    public:
        static const int N = TIME_WHEEL_NUM; // 总共有60个槽
        static const int TS = TIME_WHEEL_TS;
        tw_timer *slots[N]; // 60个槽，物理空间上是一个数组，每个数组都保存着对应槽的链表
        int cur_slot = 0;
    };
}
